package com.fhhst.prodroid;

import java.io.IOException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import android.content.Context;
import android.hardware.usb.UsbManager;
import android.util.Log;
import com.hoho.android.usbserial.driver.UsbSerialDriver;
import com.hoho.android.usbserial.driver.UsbSerialProber;
import com.hoho.android.usbserial.util.SerialInputOutputManager;

public class Printer {
	private final String TAG = "prodroidPrinter";
	private MainActivity lMainActivity;
	
	private Printcore lPrintcore;
	
	
	private boolean connected;
	private boolean online;

	public boolean isConnected() {
		return connected;
	}

	public void setConnected(boolean connected) {
		this.connected = connected;
	}

	/**
	 * The device currently in use, or {@code null}.
	 */
	private UsbSerialDriver mSerialDevice;

	/**
	 * The system's USB service.
	 */
	private UsbManager lUsbManager;

	private final ExecutorService mExecutor = Executors
			.newSingleThreadExecutor();

	private SerialInputOutputManager mSerialIoManager;

	private final SerialInputOutputManager.Listener mListener = new SerialInputOutputManager.Listener() {

		@Override
		public void onRunError(Exception e) {
			Log.d(TAG, "Runner stopped.");
		}

		@Override
		public void onNewData(final byte[] data) {
			lMainActivity.runOnUiThread(new Runnable() {
				@Override
				public void run() {
					//ainActivity.logReceivedData(data);//TODO this is unnecessary, but used for debugging purposes
					lPrintcore.updateReceivedData(data);				
					
				}
			});
		}
	};

	public Printer(Printcore aPrintcore, MainActivity aMainActivity) {
		lPrintcore=aPrintcore;
		lMainActivity = aMainActivity;
		initUSBInterface();
	   // TODO Auto-generated constructor stub
	}

	public void initUSBInterface() {
		lUsbManager = (UsbManager) lMainActivity
				.getSystemService(Context.USB_SERVICE);
	}

	public void reset() {

		// TODO Auto-generated method stub
		if (mSerialDevice != null) {
			try {
				mSerialDevice.setDTR(true);

				mSerialDevice.setDTR(false);
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}

	}

	public void pause() { //maybe we dont pause here. a service in the background is preferred
		stopIoManager();
		if (mSerialDevice != null) {
			try {
				mSerialDevice.close();

				mSerialDevice = null;

			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}

	public void resume() {
		lUsbManager = (UsbManager) lMainActivity.getSystemService(Context.USB_SERVICE);		
		mSerialDevice = UsbSerialProber.acquire(lUsbManager);
		
		Log.d(TAG, "Resumed, mSerialDevice=" + mSerialDevice);
		if (mSerialDevice == null) {
			lMainActivity.updateTitleView("No serial device.");
		} else {
			try {
				mSerialDevice.setParameters(115200, 8, 1, 0);// parameter for
																// megaadk
				mSerialDevice.open();

			} catch (IOException e) {
				Log.e(TAG, "Error setting up device: " + e.getMessage(), e);
				lMainActivity.updateTitleView("Error opening device: "
						+ e.getMessage());
				try {
					mSerialDevice.close();
				} catch (IOException e2) {
					// Ignore.
				}
				mSerialDevice = null;
				return;
			}
			lMainActivity.updateTitleView("Serial device: " + mSerialDevice);
			
			connected = true;
		}
		
		onDeviceStateChange();
	}

	private void onDeviceStateChange() {
		
		stopIoManager();
		startIoManager();
	}

	private void stopIoManager() {
		if (mSerialIoManager != null) {
			Log.i(TAG, "Stopping io manager ..");
			mSerialIoManager.stop();
			mSerialIoManager = null;
		}
	}

	private void startIoManager() {
		if (mSerialDevice != null) {
			Log.i(TAG, "Starting io manager ..");
			mSerialIoManager = new SerialInputOutputManager(mSerialDevice,
					mListener);
			mExecutor.submit(mSerialIoManager);
		}
	}
	
	
	
	public boolean send(byte[] src){
		boolean rcv =false;
		int sentBytes =0;
		
		if (mSerialDevice != null) {
			try {
				sentBytes=mSerialDevice.write(src, 20);
				
				if (sentBytes==src.length){
				  rcv = true;
				}
			} catch (IOException e) {
				Log.d(TAG, e.getMessage());
				e.printStackTrace();
			}
		}
		return rcv;
	}

	public boolean isOnline() {
		return online;
	}

	public void setOnline(boolean online) {
		this.online = online;
		lMainActivity.updateMenuTitles();
	}


}
